/*
 * Copyright (c) 2006-2022, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2022-04-09     RT-Thread    first version
 */

#include <rtthread.h>

#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include <stm32f1xx.h>

#define APPLICATION_ADDRESS 0x8007800

void (*jump2app)();

// 跳转到应用程序段
// appxaddr:用户代码起始地址.

void MSR_MSP(unsigned int addr)
{
    __asm__ volatile("MSR MSP, r0");                         //set Main Stack value
    __asm__ volatile("BX r14");
}

void iap_load_app(unsigned int appxaddr)
{
    if(((*(volatile unsigned long*)appxaddr)&0x2FFE0000)==0x20000000) //检查栈顶地址是否合法.
    {
        SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
        jump2app=(void(*)())*(volatile unsigned long*)(appxaddr+4);       //用户代码区第二个字为程序开始地址(复位地址)
        MSR_MSP(*(volatile unsigned long*)appxaddr);                  //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
        for(int i = 0; i < 8; i++)
                {
                    NVIC->ICER[i] = 0xFFFFFFFF; /* 关闭中断*/
                    NVIC->ICPR[i] = 0xFFFFFFFF; /* 清除中断标志位 */
                }

        __disable_irq();    // 关中断
        __set_CONTROL(0);    // 如果当前工程是RTOS，就要执行这句话
        jump2app();                                 //跳转到APP.
    }
}

int main(void)
{
    int count = 1;

    while (count++)
    {
        rt_kprintf("我是BootLoader 5s后我要跳转到APP程序了\n5s\n");
        rt_thread_mdelay(1000);
        rt_kprintf("4s \n");
        rt_thread_mdelay(1000);
        rt_kprintf("3s \n");
        rt_thread_mdelay(1000);
        rt_kprintf("2s \n");
        rt_thread_mdelay(1000);
        rt_kprintf("1s \n");
        rt_thread_mdelay(1000);
        rt_kprintf("jump \n");
        iap_load_app(0x8007800);
    }

    return RT_EOK;
}
